package org.kl.bpm.service.conf;

import java.sql.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.kl.bf.utils.CRUDUtils;
import org.kl.bf.utils.KLDynamicSpecifications;
import org.kl.bpm.entity.conf.BpmConfBase;
import org.kl.bpm.entity.conf.BpmDelegateInfo;
import org.kl.bpm.repository.conf.BpmConfBaseDao;
import org.kl.bpm.repository.conf.BpmDelegateInfoDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;

/**
 * 
 * @Author hqm
 * @CreateTime 2014年5月25日 下午8:40:29
 */
// Spring Bean的标识.
@Component
// 默认将类中的所有public函数纳入事务管理.
@Transactional
public class BpmDelegateInfoService {

	private BpmDelegateInfoDao bpmDelegateInfoDao;
	private BpmConfBaseDao bpmConfBaseDao;

	public BpmDelegateInfo getBpmDelegateInfo(String id) {
		return bpmDelegateInfoDao.findOne(id);
	}

	public void saveBpmDelegateInfo(BpmDelegateInfo entity) {
		bpmDelegateInfoDao.save(entity);
	}

	public void deleteBpmDelegateInfo(String id) {
		bpmDelegateInfoDao.delete(id);
	}

	public List<BpmDelegateInfo> getAllBpmDelegateInfo() {
		return bpmDelegateInfoDao.findAll();
	}

	/**
	 * 按条件查询
	 */
	public List<BpmDelegateInfo> getAllBpmDelegateInfo(Map<String, Object> searchParams, String sortType,
			String orderType) {
		Specification<BpmDelegateInfo> spec = KLDynamicSpecifications.buildSpecification(searchParams,
				BpmDelegateInfo.class);
		return bpmDelegateInfoDao.findAll(spec, CRUDUtils.buildSort(sortType, orderType));
	}

	public BpmDelegateInfo findByAssigneeAndStatus(String assignee, String targetProcessDefinitionId) {
		List<BpmDelegateInfo> bdiList = bpmDelegateInfoDao.findByAssigneeIdAndStatus(assignee, 1);
		if (StringUtils.isNotBlank(targetProcessDefinitionId)) {
			BpmConfBase bpmConfBase = bpmConfBaseDao.findByProcessDefinitionId(targetProcessDefinitionId);
			for (BpmDelegateInfo bdi : bdiList) {
				if (timeNotBetweenNow(bdi.getStartTime(), bdi.getEndTime())) {
					if (endTimeBeforeNow(bdi.getEndTime())) {
						bdi.setStatus(0);// 如果截止时间小于当前时间则将其设为无效
						bpmDelegateInfoDao.save(bdi);
					}
					continue;
				}
				if ((bdi.getBpmProcess() == null)
						|| bdi.getBpmProcess().getBpmConfBase().getProcessDefinitionKey()
								.equals(bpmConfBase != null ? bpmConfBase.getProcessDefinitionKey() : "")) {
					return bdi;
				}
			}
		}
		return null;
	}

	public Page<BpmDelegateInfo> getUserBpmDelegateInfo(Map<String, Object> searchParams, int pageNumber, int pageSize,
			String sortType, String orderType) {
		PageRequest pageRequest = CRUDUtils.buildPageRequest(pageNumber, pageSize, sortType, orderType);
		Specification<BpmDelegateInfo> spec = buildSpecification(searchParams);

		return bpmDelegateInfoDao.findAll(spec, pageRequest);
	}

	/**
	 * 创建动态查询条件组合.
	 */
	private Specification<BpmDelegateInfo> buildSpecification(Map<String, Object> searchParams) {
		Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
		Specification<BpmDelegateInfo> spec = DynamicSpecifications.bySearchFilter(filters.values(),
				BpmDelegateInfo.class);
		return spec;
	}

	private boolean timeNotBetweenNow(Date startTime, Date endTime) {
		Date now = new Date(new DateTime().getMillis());

		if (startTime != null) {
			return now.before(startTime);
		}

		if (endTime != null) {
			return now.after(endTime);
		}

		return false;
	}

	private boolean endTimeBeforeNow(Date endTime) {
		Date now = new Date(new DateTime().getMillis());
		if (endTime != null) {
			return now.after(endTime);
		}
		return false;
	}

	@Autowired
	public void setBpmDelegateInfoDao(BpmDelegateInfoDao bpmDelegateInfoDao) {
		this.bpmDelegateInfoDao = bpmDelegateInfoDao;
	}

	@Autowired
	public void setBpmConfBaseDao(BpmConfBaseDao bpmConfBaseDao) {
		this.bpmConfBaseDao = bpmConfBaseDao;
	}

}
